#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Blueprint, request, current_app, g
from werkzeug.exceptions import BadRequest
from applications.models.user import User
from applications.extensions.db_plugin import db
from flask_jwt_extended import create_access_token, create_refresh_token
from common.core.make_response import (
    make_success, make_error, make_validation_error, make_server_error, make_unauthorized)
from applications.extensions.jwt_plugin import jwt_required_with_user
from applications.extensions.redis_plugin import redis_client
from common.utils.send_verify_code import send_email_code
from common.utils.helpers import now_beijing

auth_bp = Blueprint('auth', __name__, url_prefix='/api/auth')


@auth_bp.route('/login', methods=['POST'])
def login():
    """
    用户登录
    :return:
    """
    try:
        data = request.get_json(force=True)
        current_app.logger.info(f'请求登陆接口：{data}')

        if not data:
            return make_validation_error()

        username = data.get('username')
        password = data.get('password')

        # 查询用户
        user = User.query.filter_by(username=username).first()
        if not user:
            current_app.logger.error(f'登录失败：用户不存在 -> {username}')
            return make_error("输入的账号不存在，如需登录请先注册~")

        # 校验密码
        if not user.check_password(password):
            current_app.logger.warning(f'登录失败：密码错误 -> 用户名：{username}')
            return make_error("用户名或密码错误，请检查！")

        # 创建 token
        access_token = create_access_token(identity=str(user.id))
        refresh_token = create_refresh_token(identity=str(user.id))

        # 返回成功响应
        response_data = {
            "access_token": access_token,
            "refresh_token": refresh_token
        }
        current_app.logger.info(f'用户登录成功：uid={user.id}，username={username}')
        return make_success(data=response_data, msg="登录成功")

    except BadRequest as e:
        current_app.logger.error(f'登录失败：请求体 JSON 解析失败 -> {e}')
        return make_validation_error()

    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"登录失败：服务器异常 -> {e}")
        return make_server_error()


@auth_bp.route('/register', methods=['POST'])
def register():
    """
    注册账号
    :return:
    """
    try:
        data = request.get_json(force=True)
        current_app.logger.info(f'请求登陆接口：{data}')

        username = data.get("username")
        phone = data.get("phone")
        email = data.get("email")
        password = data.get("password")

        # 校验参数
        if not username or not password:
            return make_validation_error()
        if User.query.filter_by(username=username).first():
            return make_error("您输入的用户名已存在，请更换！")
        if User.query.filter_by(phone=data['phone']).first():
            return make_error("您输入的手机号已被绑定！")
        if User.query.filter_by(email=data['email']).first():
            return make_error("您输入的邮箱已被绑定！")

        # 创建用户对象
        user = User(username=username, phone=phone, email=email)
        user.set_password(password)

        # 提交事务
        db.session.add(user)
        db.session.commit()

        current_app.logger.info(f"用户注册成功：username={username}")
        return make_success(msg="注册成功")

    except BadRequest as e:
        current_app.logger.error(f"注册失败：请求体不是合法 JSON -> {e}")
        return make_validation_error()

    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"注册失败：服务器异常 -> {e}")
        return make_server_error()


@auth_bp.route('/reset/password', methods=['POST'])
def reset_password():
    """
    重置密码：admin用户可直接根据用户名修改密码，普通用户需要根据旧密码或邮箱验证码修改
    :return:
    """
    try:
        data = request.get_json(force=True)
        current_app.logger.info(f'请求修改密码接口：{data}')

        username = data.get('username')
        old_password = data.get('old_password')
        new_password = data.get('new_password')
        verify_code = data.get('verify_code')
        mode = data.get('mode')

        # 参数校验
        if not all([username, new_password]):
            current_app.logger.error("修改密码失败：缺少必要参数")
            return make_validation_error()

        user = User.query.filter_by(username=username).first()

        if not user:
            current_app.logger.error(f'修改密码失败：用户不存在 -> {username}')
            return make_error("用户不存在")

        if user.id != 0:
            if mode == "email":
                if not verify_code:
                    current_app.logger.error("修改密码失败：缺少验证码")
                    return make_validation_error()
                redis_code = redis_client.get(name=f"email:code:reset:{user.email}")
                if verify_code != redis_code:
                    current_app.logger.error(
                        f'修改密码失败：[{username}]验证码错误 -> 输入的[{verify_code}] - 实际的[{redis_code}]')
                    return make_error("验证码错误")
            elif mode == "password":
                if not old_password:
                    current_app.logger.error("修改密码失败：缺少旧密码")
                    return make_validation_error()
                if not user.check_password(old_password):
                    current_app.logger.error(f'修改密码失败：旧密码错误 -> {username}')
                    return make_error("旧密码错误")
            else:
                current_app.logger.error("修改密码失败：缺少验证方式")
                return make_validation_error()

        user.set_password(new_password)
        db.session.commit()
        current_app.logger.info(f"用户修改密码成功：username={username}")
        return make_success(msg="修改密码成功")

    except Exception as e:
        db.session.rollback()  # 回滚事务
        current_app.logger.error(f"修改密码失败：服务器异常 -> {e}", exc_info=True)
        return make_server_error()


@auth_bp.route('/verify/code', methods=['POST'])
def send_verify_code():
    """
    发送验证码
    :return:
    """
    try:
        data = request.get_json(force=True)
        username = data.get('username')
        mode = data.get('mode')
        current_app.logger.info(f'请求发送验证码接口：{data}')

        if mode not in ["register", "login", "reset"]:
            return make_validation_error()

        user = User.query.filter_by(username=username).first()
        if not user:
            current_app.logger.error(f'验证码发送失败：用户不存在 -> {username}')
            return make_error("用户不存在")

        user_email = user.email
        result = send_email_code(redis_client=redis_client, email=user_email, purpose=mode)

        if result['success']:
            return make_success(msg=result['msg'])
        else:
            return make_error(msg=result['msg'])

    except Exception as e:
        current_app.logger.error(f'发送验证码失败: {str(e)}')
        return make_server_error(msg="服务器异常，请稍后再试")


@auth_bp.route('/info', methods=['GET'])
@jwt_required_with_user()
def get_user_info():
    """获取用户信息"""
    current_user = g.user
    if not current_user:
        return make_unauthorized()
    user = User.query.get_or_404(current_user.id)
    user_dict = {
        "username": user.username,
        "phone": user.phone,
        "email": user.email,
        "avatar": user.avatar,
        "create_time": user.create_time.strftime("%Y-%m-%d %H:%M:%S")
    }
    return make_success(data=user_dict)


@auth_bp.route('/update', methods=['PUT'])
@jwt_required_with_user()
def update_user_info():
    """
    更新用户信息
    :return:
    """
    try:
        data = request.get_json(force=True)
        current_app.logger.info(f'请求更新用户信息接口：{data}')

        # 获取当前用户
        current_user = g.user
        if not current_user:
            return make_unauthorized()

        user = User.query.get_or_404(current_user.id)

        # 获取要更新的字段
        username = data.get('username')
        phone = data.get('phone')
        email = data.get('email')
        avatar = data.get('avatar')

        # 检查用户名唯一性
        if username and username != user.username:
            existing_user = User.query.filter_by(username=username).first()
            if existing_user:
                return make_error("用户名已存在，请更换！")
            user.username = username

        # 检查手机号唯一性
        if phone and phone != user.phone:
            existing_user = User.query.filter_by(phone=phone).first()
            if existing_user:
                return make_error("手机号已被绑定！")
            user.phone = phone

        # 检查邮箱唯一性
        if email and email != user.email:
            existing_user = User.query.filter_by(email=email).first()
            if existing_user:
                return make_error("邮箱已被绑定！")
            user.email = email

        # 更新头像
        if avatar is not None:
            user.avatar = avatar

        user.update_time = now_beijing()
        # 提交事务
        db.session.commit()

        current_app.logger.info(f"用户信息更新成功：uid={user.id}，username={user.username}")
        return make_success(msg="用户信息更新成功")

    except BadRequest as e:
        current_app.logger.error(f"更新用户信息失败：请求体 JSON 解析失败 -> {e}")
        return make_validation_error()

    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"更新用户信息失败：服务器异常 -> {e}")
        return make_server_error()
